package view;

import domein.MessageObservable;
import domein.OnlineUsersObservable;
import domein.Server;
import domein.StateObservable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 *
 * @author Colin Bundervoet
 * @author Jeroen Pattyn
 */
public class ServerFrame extends JFrame implements ActionListener, Observer
{
    private Server server;
    private Thread serverThread;
    private JLabel lblPort, lblServerLog, lblUsers;
    private JTextField txtPort;
    private JButton btnStartServer, btnStopServer;
    private JTextArea txtAreaServerLog;
    private JList lstOnlineUsers;
    JScrollPane scrlPaneServerLog, scrlPaneOnlineUsers;
    private JCheckBox checkLocalHost;

    /**
     * Default constructor for ServerFrame
     */
    public ServerFrame() {
        super("ChIrc - Server");

        this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        this.setSize(500, 300);
        this.setLocationRelativeTo(null);

        initComponents();
        setLayout();

        server = new Server();
        server.addServerLogObserver(this);
        server.addOnlineUsersObserver(this);
        server.addStateObserver(this);

        setInitialState();
    }

    private void initComponents() {
        lblPort = new JLabel("Port number:");
        lblServerLog = new JLabel("Server Log");
        lblUsers = new JLabel("Connected Users");

        txtPort = new JTextField();
        txtPort.setText("5000");
        btnStartServer = new JButton("Start server");
        btnStartServer.addActionListener(this);
        btnStopServer = new JButton("Stop server");
        btnStopServer.addActionListener(this);
        txtAreaServerLog = new JTextArea();
        lstOnlineUsers = new JList();
        lstOnlineUsers.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e) {
                JPopupMenu popupMenu = new JPopupMenu();
                JMenuItem kickButton, whoIsButton, opButton, deOpButton, banButton;
                popupMenu.add(kickButton = new JMenuItem("Kick"));
                popupMenu.add(whoIsButton = new JMenuItem("Whois"));
                popupMenu.add(opButton = new JMenuItem("Set op"));
                popupMenu.add(deOpButton = new JMenuItem("De-op"));
                popupMenu.add(banButton = new JMenuItem("Ban"));
                kickButton.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        server.kick(lstOnlineUsers.getSelectedValue().toString());
                    }
                });
                whoIsButton.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        server.whois(lstOnlineUsers.getSelectedValue().toString());
                    }
                });
                banButton.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        server.ban(lstOnlineUsers.getSelectedValue().toString());
                    }
                });
                opButton.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        server.op(lstOnlineUsers.getSelectedValue().toString());
                    }
                });
                deOpButton.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        server.deop(lstOnlineUsers.getSelectedValue().toString());
                    }
                });

                if (SwingUtilities.isRightMouseButton(e)
                    && !lstOnlineUsers.isSelectionEmpty() && lstOnlineUsers.locationToIndex(e.getPoint()) == lstOnlineUsers.getSelectedIndex()) {
                    popupMenu.show(lstOnlineUsers, e.getX(), e.getY());
                }
            }
        });

        scrlPaneServerLog = new JScrollPane();
        scrlPaneServerLog.setViewportView(txtAreaServerLog);
        scrlPaneOnlineUsers = new JScrollPane();
        scrlPaneOnlineUsers.setViewportView(lstOnlineUsers);
        checkLocalHost = new JCheckBox("Localhost");

    }

    private void setLayout() {
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(scrlPaneServerLog, javax.swing.GroupLayout.PREFERRED_SIZE, 459, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                .addComponent(lblPort, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addComponent(lblServerLog, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(19, 19, 19)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                .addComponent(btnStartServer, javax.swing.GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE)
                .addComponent(btnStopServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(18, 18, 18)))
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(checkLocalHost, javax.swing.GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE)
                .addGroup(layout.createSequentialGroup()
                .addGap(63, 63, 63)
                .addComponent(lblUsers, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGroup(layout.createSequentialGroup()
                .addGap(18, 18, 18)
                .addComponent(scrlPaneOnlineUsers, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)))
                .addContainerGap()));
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblPort, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(btnStartServer).addComponent(checkLocalHost))
                .addGap(8, 8, 8)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblServerLog)
                .addComponent(lblUsers, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(btnStopServer))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(scrlPaneOnlineUsers, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE)
                .addComponent(scrlPaneServerLog, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE))
                .addContainerGap()));
        pack();
    }

    private void setInitialState() {
        btnStopServer.setEnabled(false);
        txtAreaServerLog.setEditable(false);
        checkLocalHost.setSelected(false);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == btnStartServer) {
            final String port = txtPort.getText();
            serverThread = new Thread()
            {
                @Override
                public void run() {
                    server.start(port, checkLocalHost.isSelected());
                }
            };
            serverThread.start();
        }
        else if (e.getSource() == btnStopServer) {
            server.stop();
            serverThread = null;
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o.getClass() == MessageObservable.class) {
            txtAreaServerLog.append(arg.toString());
            JScrollBar s = scrlPaneServerLog.getVerticalScrollBar();
            s.setValue(s.getMaximum());
        }
        else if (o.getClass() == OnlineUsersObservable.class) {
            lstOnlineUsers.setListData(((OnlineUsersObservable) o).getOnlineUsers());
            lstOnlineUsers.repaint();
        }
        else if (o.getClass() == StateObservable.class) {
            if (((StateObservable) o).getState()) {
                txtPort.setEnabled(false);
                btnStartServer.setEnabled(false);
                btnStopServer.setEnabled(true);
            }
            else {
                txtPort.setEnabled(true);
                btnStartServer.setEnabled(true);
                btnStopServer.setEnabled(false);
            }
        }
    }
}
